package sg.edu.ntu.sci.blackboard.agilix;

import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.commons.httpclient.Header;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.NameValuePair;
import org.apache.commons.httpclient.methods.HeadMethod;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import sg.edu.ntu.sci.blackboard.agilix.model.Doc;
import sg.edu.ntu.sci.blackboard.agilix.util.IOUtil;

/**
 * This class resolves the link in a Blackboard document of type Learning Object
 * (Learning Object is the company behind blog service in Blackboard). It is 
 * assumed that each LO document has a link to the blog service, which is
 * publicly accessible
 *
 * @author ngocgiang
 */
public class LODocumentResolver {

    private static Log log = LogFactory.getLog(LODocumentResolver.class);

    private String location; // location to the "1" folder
    private HttpClient client;

    private void initialize() {
        client = new HttpClient();
    }

    public LODocumentResolver() {
        initialize();
        location = System.getProperty("user.home") + "\\Application Data\\Blackboard\\Backpack\\1";
    }

    public LODocumentResolver(String location) {
        initialize();
        this.location = location;
    }

    /**
     * Resolve the crawlable link
     * @param document LO document
     * @return crawlable link
     */
    public String resolve(Doc document) throws IOException {
        String fragmentLocation = location + "\\" + document.getFolder() + "\\" + document.getFile();
        String fragmentContent = IOUtil.readFile(fragmentLocation);
        String regex = "http://[a-zA-Z_0-9\\-]+(\\.\\w[a-zA-Z_0-9\\-]+)+(/[#&\\n\\-=?\\+\\%;/\\.\\w]+)?";
        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(fragmentContent);
        if (matcher.find()) {
            int start = matcher.start();
            int end = matcher.end();
            String url = fragmentContent.substring(start, end);
            url = url.replaceAll("&amp;", "&");
            url = url.replaceAll("http://", "");
            url = resolveLink(url);
            return url;
        }
        return null;
    }

    private String resolveLink(String url) {
        try {
            String host = url.substring(0, url.indexOf("/"));
            client.getHostConfiguration().setHost(host);
            String path = url.substring(url.indexOf("/"), url.indexOf("?"));
            HeadMethod head = new HeadMethod(path);
            String paramStrBig = url.substring(url.indexOf("?") + 1);
            String[] paramStrs = paramStrBig.split("&");
            Map<String, String> params = new HashMap<String, String>();
            for (String paramStr : paramStrs) {
                String[] pair = paramStr.split("=");
                params.put(pair[0], pair[1]);
            }
            updateHeadParameters(head, params);
            head.setFollowRedirects(false);
            client.executeMethod(head);
            Header newLocation = head.getResponseHeader("Location");
            return newLocation.getValue();
        } catch (Exception e) {
            log.error("Error in resolving link", e);
        }
        return null;
    }

    private static void updateHeadParameters(HeadMethod method, Map<String, String> params) {
		if (params != null) {
			Set<Map.Entry<String, String>> paramEntries = params.entrySet();
			NameValuePair[] namevalues = new NameValuePair[paramEntries.size()];
			int i = 0;
			for (Iterator<Map.Entry<String, String>> iter = paramEntries.iterator(); iter.hasNext();) {
				Map.Entry<String, String> param = iter.next();
				namevalues[i++] = new NameValuePair(param.getKey(), param.getValue());
			}
			method.setQueryString(namevalues);
		}
	}
}
